package com.whcoding.task.xxl.job.task.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.whcoding.task.xxl.job.po.OrmDeptPO;
import com.whcoding.task.xxl.job.po.TaskerErrorDataPO;
import com.whcoding.task.xxl.job.task.base.BaseTasker;
import com.whcoding.task.xxl.job.task.base.ErrorDataInfo;
import com.xxl.job.core.log.XxlJobLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.whcoding.task.xxl.job.task.utils.TaskRedisConstant.REDIS_WH_PREFIX;

@Service
public class TrackTasker extends BaseTasker<OrmDeptPO> {
    private static final Logger logger = LoggerFactory.getLogger(TrackTasker.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /**
     * 数据的批量业务处理
     *
     * @param list 数据
     */
    @Override
    protected void taskRunnable(List<OrmDeptPO> list) {
        long begin = System.currentTimeMillis();
        XxlJobLogger.log("开始处理task数据");
        try {
            //保存数据到数据库
            this.saveToDB(list);
            //保存数据到Redis
            this.saveToRedis(list);
        } catch (Exception e) {
            logger.error("[railway] taskRunnable failed", e);
            throw e;
        }
        logger.info("[railway] task done!time={}", (System.currentTimeMillis() - begin));
        XxlJobLogger.log("结束处理task数据");
    }

    /**
     * 保存到数据库中
     *
     * @param ormDeptPOS
     */
    private synchronized void saveToDB(List<OrmDeptPO> ormDeptPOS) {
        XxlJobLogger.log("开始保存数据到数据库");
        logger.debug("ormDeptPOS={}", JSONObject.toJSONString(ormDeptPOS));
        XxlJobLogger.log("结束保存数据到数据库");
    }

    /**
     * 数据保存到redis
     * @author ZhouWenHao
     * @date 2023/04/04 9:15
     * @param deptPOList
     */
    private void saveToRedis(List<OrmDeptPO> deptPOList) {
        logger.debug("saveToRedisIot, size={}", deptPOList.size());
        //按照箱号去重，取最新的一条
        Map<String, OrmDeptPO> collect = deptPOList.stream().collect(Collectors.toMap(OrmDeptPO::getDeptNo, t -> t, this::compareByCreateTime));
        logger.debug("saveToRedisIot 去重完毕");
        //转成redis需要的结构
        Map<String, String> redisMap = Maps.newHashMap();
        for (Map.Entry<String, OrmDeptPO> entry : collect.entrySet()) {
            redisMap.put(REDIS_WH_PREFIX + entry.getKey(), JSON.toJSONString(JSON.toJSONString(entry.getValue())));
        }
        logger.debug("IOT[railway] saveToRedisIot map转换完毕");
        //保存到redis中
        redisTemplate.opsForValue().multiSet(redisMap);
        logger.debug("IOT[railway] saveToRedisIot 保存到redis完毕");
    }

    /**
     * 通过创建时间排序定位对象并返回最新的
     *
     * @author ZhouWenHao
     * @date 2023/04/04 9:15
     */
    private OrmDeptPO compareByCreateTime(OrmDeptPO t1, OrmDeptPO t2) {
        if (null != t1.getCreateTime()
                && null != t2.getCreateTime()
                && t1.getCreateTime().after(t2.getCreateTime())) {
            return t1;
        }
        return t2;
    }


    /**
     * 异常数据的回调函数-入库
     *
     * @param errorDataInfo 异常信息
     * @author ZhouWenHao
     * @date 2023/04/04 9:15
     */
    @Override
    protected void errorDataCallback(ErrorDataInfo<OrmDeptPO> errorDataInfo) {
        TaskerErrorDataPO taskerErrorDataPO = new TaskerErrorDataPO()
                .setCreatedAt(new Date())
                .setData(JSON.toJSONString(errorDataInfo.getList()))
                .setRetryTimes(errorDataInfo.getRetryTimes())
                .setErrorMsg(errorDataInfo.getE().getMessage())
                .setDataType(1);
        //TODO 失败信息保存到数据库中
    }
}
